﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Windows;
using Microsoft.Phone.Net.NetworkInformation;
using Microsoft.Phone.Tasks;
using Store.WP7.Data;
using Store.WP7.Data.WebStore;
using Store.WP7.Framework;
using Store.WP7.Framework.ErrorManagement;
using Store.WP7.Framework.Settings;

namespace Store.WP7.ViewModels
{
    public class MainPageViewModel : PageViewModelBase
    {
        #region Private Fields

        private readonly StoreService _storeService;
        private readonly AppSettings _appSettings;

        #endregion

        #region Commands

        public RelayCommand GoToSettingsCommand { get; private set; }
        public RelayCommand GoToInfosCommand { get; private set; }
        public RelayCommand RateAppCommand { get; private set; }
        public RelayCommand SendMailCommand { get; private set; }

        #endregion

        #region Ctors

        public MainPageViewModel()
        {
            _storeService = new StoreService();
            _appSettings = AppSettings.Load();

            GoToSettingsCommand = new RelayCommand(GoToSettings);
            GoToInfosCommand = new RelayCommand(GoToInfos);
            RateAppCommand = new RelayCommand(RateApp);
            SendMailCommand = new RelayCommand(SendMail);
        }

        #endregion

        #region Events

        public override void OnNavigatedTo(System.Windows.Navigation.NavigationService navigationService, System.Windows.Navigation.NavigationContext navigationContext, System.Collections.Generic.IDictionary<string, object> state, System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(navigationService, navigationContext, state, e);

            if (NavigationContext.QueryString.ContainsKey("go"))
            {
                string goTo = NavigationContext.QueryString["go"];
                if (goTo == "basket")
                {
                    PanoramaIndex = 2;
                }
                else if (goTo == "orders")
                {
                    AreOrdersLoaded = false;
                    PanoramaIndex = 1;
                }

                if (NavigationContext.QueryString.ContainsKey("productId"))
                {
                    string sProductId = NavigationContext.QueryString["productId"];
                    int pid = -1;
                    if (int.TryParse(sProductId, out pid))
                    {
                        AddProductToBasket(pid);
                    }
                }
            }
            else
            {
                PanoramaIndex = 0;
            }

            CheckConnection();

            LoadSelectedPanorama();
            LoadBasket();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Checks the data connection
        /// </summary>
        private void CheckConnection()
        {
            if (!NetworkInterface.GetIsNetworkAvailable())
            {
                ErrorManager.HandleError(ErrorType.NoConnection);
            }
        }

        private void LoadProducts()
        {
            //UI Thread
            if (AreProductsLoaded)
            {
                return;
            }

            BusyMessage = "chargement des produits en cours";
            BusyCounter++;

            if (NetworkInterface.GetIsNetworkAvailable())
            {
                System.Diagnostics.Debug.WriteLine("chargement des produits...");
                _storeService.LoadHomeProductsAsync(callback =>
                {
                    //Worker thread du ThreadPool
                    if (callback.Error == null)
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            //UI Thread
                            Products.Clear();
                        });

                        //Worker thread du ThreadPool
                        var products = callback.Result;
                        CacheManager.Current.Remove(AppSettingsKeyNames.HomeProducts);
                        CacheManager.Current.Add(AppSettingsKeyNames.HomeProducts, products, TimeSpan.FromMinutes(60));

                        foreach (var p in products)
                        {
                            var viewModel = new ProductViewModel(p);
                            Deployment.Current.Dispatcher.BeginInvoke(() =>
                            {
                                //UI Thread
                                Products.Add(viewModel);
                            });
                            System.Threading.Thread.Sleep(20);
                        }

                        //Worker thread du ThreadPool
                        StoreCache.Instance.UpdateProducts(products);

                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            //UI Thread
                            BusyCounter--;
                            BusyMessage = "";
                            AreProductsLoaded = true;
                        });
                    }
                    else
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            BusyCounter--;
                            ErrorManager.HandleError(ErrorType.WebServiceCallbackFail, callback.Error);
                        });
                    }
                });
            }
            else
            {
                var productsHome = CacheManager.Current.Get<List<Product>>(AppSettingsKeyNames.HomeProducts);
                if (productsHome != null)
                {
                    Products.Clear();

                    foreach (var p in productsHome)
                    {
                        var viewModel = new ProductViewModel(p);
                        Products.Add(viewModel);
                        System.Threading.Thread.Sleep(20);
                    }

                    StoreCache.Instance.UpdateProducts(productsHome);

                    BusyCounter--;
                    BusyMessage = "";
                    AreProductsLoaded = true;
                }
            }
        }

        private void LoadOrders()
        {
            if (AreOrdersLoaded)
            {
                BusyMessage = "chargement des commandes en cours";
                return;
            }

            BusyCounter++;
            BusyMessage = "chargement des commandes en cours";

            if (NetworkInterface.GetIsNetworkAvailable())
            {
                System.Diagnostics.Debug.WriteLine("Loading orders ...");
                int customerId = _appSettings.CustomerId;

                _storeService.LoadHomeOrdersAsync(customerId, serviceResult =>
                {
                    if (serviceResult.Error == null)
                    {
                        var orders = serviceResult.Result;
                        CacheManager.Current.Remove(AppSettingsKeyNames.HomeOrders);
                        CacheManager.Current.Add(AppSettingsKeyNames.HomeOrders, orders, TimeSpan.FromMinutes(60));

                        Deployment.Current.Dispatcher.BeginInvoke(() => Orders.Clear());

                        foreach (var order in orders)
                        {
                            var orderViewModel = new OrderViewModel(order);
                            Deployment.Current.Dispatcher.BeginInvoke(() =>
                            {
                                Orders.Add(orderViewModel);
                            });
                            Thread.Sleep(20);
                        }

                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            BusyCounter--;
                            BusyMessage = "";
                            AreOrdersLoaded = true;
                        });
                    }
                    else
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            BusyCounter--;
                            ErrorManager.HandleError(ErrorType.WebServiceCallbackFail, serviceResult.Error);
                        });
                    }
                });
            }
            else
            {
                var ordersHome = CacheManager.Current.Get<List<Order>>(AppSettingsKeyNames.HomeOrders);
                if (ordersHome != null)
                {
                    foreach (var order in ordersHome)
                    {
                        var orderViewModel = new OrderViewModel(order);
                        Orders.Add(orderViewModel);
                        Thread.Sleep(20);
                    }

                    BusyCounter--;
                    BusyMessage = "";
                    AreOrdersLoaded = true;
                }
            }
        }

        private void LoadBasket()
        {
            if (isBasketLoaded)
                return;

            IsBasketEmpty = true;
            BusyCounter++;
            BusyMessage = "chargement du panier en cours";

            var basketHome = CacheManager.Current.Get<List<Product>>(AppSettingsKeyNames.Basket);
            if (basketHome != null)
            {
                Deployment.Current.Dispatcher.BeginInvoke(() => BasketProducts.Clear());

                foreach (var product in basketHome)
                {
                    var pm = new ProductViewModel(product);
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        BasketProducts.Add(pm);
                    });
                    Thread.Sleep(20);
                }

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    IsBasketEmpty = false;
                    BusyCounter--;
                    BusyMessage = "";
                    isBasketLoaded = true;
                });
            }
            else
            {
                Deployment.Current.Dispatcher.BeginInvoke(() =>
                {
                    BasketProducts.Clear();
                    BusyCounter--;
                    BusyMessage = "";
                    isBasketLoaded = true;
                });
            }
        }

        private ObservableCollection<ProductViewModel> _BasketProducts = new ObservableCollection<ProductViewModel>();
        public ObservableCollection<ProductViewModel> BasketProducts
        {
            get { return _BasketProducts; }
        }

        private void AddProductToBasket(int productId)
        {
            BusyCounter++;
            BusyMessage = "ajout du panier au panier en cours";

            var product = _BasketProducts.FirstOrDefault(p => p.Id == productId);
            if (product == null)
            {
                System.Diagnostics.Debug.WriteLine("Adding product to basket ...");
                _storeService.LoadProductAsync(productId, callback =>
                {
                    if (callback.Error == null)
                    {
                        var pm = new ProductViewModel(callback.Result);

                        var basket = new List<Product>();
                        foreach (var p in BasketProducts)
                        {
                            basket.Add(p.InnetProduct);
                        }

                        basket.Add(callback.Result);
                        CacheManager.Current.Remove(AppSettingsKeyNames.Basket);
                        CacheManager.Current.Add(AppSettingsKeyNames.Basket, basket, TimeSpan.FromMinutes(60));

                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            BasketProducts.Add(pm);
                        });

                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            IsBasketEmpty = false;
                            BusyCounter--;
                            BusyMessage = "";
                        });
                    }
                    else
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() =>
                        {
                            BusyCounter--;
                            ErrorManager.HandleError(ErrorType.WebServiceCallbackFail, callback.Error);
                        });
                    }
                });
            }
            else
            {
                //product already added
                BusyCounter--;
            }
        }

        #endregion

        #region Public Properties

        private readonly ObservableCollection<ProductViewModel> _products = new ObservableCollection<ProductViewModel>();

        /// <summary>
        /// Gets all products
        /// </summary>
        public ObservableCollection<ProductViewModel> Products
        {
            get
            {
                return _products;
            }
        }

        private readonly ObservableCollection<OrderViewModel> _orders = new ObservableCollection<OrderViewModel>();

        /// <summary>
        /// Gets all user's orders
        /// </summary>
        public ObservableCollection<OrderViewModel> Orders
        {
            get
            {
                return _orders;
            }
        }

        private OrderViewModel _selectedOrder;
        /// <summary>
        /// Selected order
        /// </summary>
        public OrderViewModel SelectedOrder
        {
            get { return _selectedOrder; }
            set
            {
                _selectedOrder = value;
                RaisePropertyChanged(() => SelectedOrder);

                OnOrdersSelectionChanged();
            }
        }

        private ProductViewModel _selectedProduct;
        /// <summary>
        /// Selected product
        /// </summary>
        public ProductViewModel SelectedProduct
        {
            get { return _selectedProduct; }
            set
            {
                _selectedProduct = value;
                RaisePropertyChanged(() => SelectedProduct);

                OnProductsSelectionChanged();
            }
        }

        private int panoramaIndex;
        public int PanoramaIndex
        {
            get { return panoramaIndex; }
            set
            {
                if (panoramaIndex != value)
                {
                    panoramaIndex = value;
                    RaisePropertyChanged(() => this.PanoramaIndex);

                    LoadSelectedPanorama();
                }
            }
        }

        private int busyCounter;
        /// <summary>
        /// Counter for busy tasks
        /// </summary>
        public int BusyCounter
        {
            get { return busyCounter; }
            set
            {
                if (busyCounter != value)
                {
                    busyCounter = value;

                    IsBusy = busyCounter > 0;
                }
            }
        }

        private bool isBasketLoaded = false;

        private bool _areProductsLoaded;
        public bool AreProductsLoaded
        {
            get { return _areProductsLoaded; }
            set
            {
                if (_areProductsLoaded != value)
                {
                    _areProductsLoaded = value;
                    RaisePropertyChanged(() => this.AreProductsLoaded);
                }
            }
        }

        private bool _areOrdersLoaded;
        public bool AreOrdersLoaded
        {
            get { return _areOrdersLoaded; }
            set
            {
                if (_areOrdersLoaded != value)
                {
                    _areOrdersLoaded = value;
                    RaisePropertyChanged(() => this.AreOrdersLoaded);
                }
            }
        }

        private bool _IsBasketEmpty;
        public bool IsBasketEmpty
        {
            get { return _IsBasketEmpty; }
            set
            {
                if (_IsBasketEmpty != value)
                {
                    _IsBasketEmpty = value;
                    RaisePropertyChanged(() => IsBasketEmpty);
                }
            }
        }

        #endregion

        #region Public Methods

        public void LoadSelectedPanorama()
        {
            if (PanoramaIndex == 0)
            {
                LoadProducts();
            }
            else if (PanoramaIndex == 1)
            {
                LoadOrders();
            }
        }

        public void OnOrdersSelectionChanged()
        {
            if (SelectedOrder != null)
            {
                NavigationService.Navigate(new System.Uri(string.Format("/Views/OrderDetailsPage.xaml?orderId={0}", SelectedOrder.Id), System.UriKind.Relative));
                // To unselect the item from the list
                SelectedOrder = null;
            }
        }

        public void OnProductsSelectionChanged()
        {
            if (SelectedProduct != null)
            {
                NavigationService.Navigate(new System.Uri(string.Format("/Views/ProductDetailsView.xaml?productId={0}", SelectedProduct.Id), System.UriKind.Relative));
            }
        }

        public void OnGoToMoreProductsView()
        {
            NavigationService.Navigate(new System.Uri("/Views/ProductsView.xaml", System.UriKind.Relative));
        }

        public void OnGoToMoreOrdersView()
        {
            NavigationService.Navigate(new System.Uri("/Views/OrdersView.xaml", System.UriKind.Relative));
        }

        public void OnGoToCheckOutView()
        {
            //trick to extend cache for basket
            var currentBasket = CacheManager.Current.Get<List<Product>>(AppSettingsKeyNames.Basket);
            if (currentBasket != null)
            {
                CacheManager.Current.Remove(AppSettingsKeyNames.Basket);
                CacheManager.Current.Add(AppSettingsKeyNames.Basket, currentBasket, TimeSpan.FromMinutes(10));
            }

            NavigationService.Navigate(new System.Uri("/Views/CheckoutView.xaml", System.UriKind.Relative));
        }

        public void GoToSettings()
        {
            NavigationService.Navigate(new System.Uri("/Views/SettingsView.xaml", System.UriKind.Relative));
        }

        public void GoToInfos()
        {
            NavigationService.Navigate(new System.Uri("/Views/AboutView.xaml", System.UriKind.Relative));
        }

        public void RateApp()
        {
            try
            {
                new MarketplaceReviewTask().Show();
            }
            catch { }
        }

        public void SendMail()
        {
            var mail = new EmailComposeTask();
            mail.To = "suggestions@mystore.com";
            mail.Subject = "My Store - Suggestions";
            mail.Body = "";

            try
            {
                mail.Show();
            }
            catch { }
        }

        #endregion
    }
}
